.TITLE MTDRV .IDENT /05.08/ ; ; Copyright (c) 1995-1999 by Mentec, Inc., U.S.A. ; All rights reserved ; ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED ; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; VERSION 05.08 ; ; SCOTT G. DAVIS 9-JUL-74 ; ; PREVIOUSLY MODIFIED BY: ; ; P. J. BEZEREDI ; D. N. CUTLER ; S. G. DAVIS ; C. A. D'ELIA ; B. LYONS ; T. J. MILLER ; F. L. STRAIGHT ; ; MODIFIED BY: ; ; ; ; PB122 -- RETURN IS.SUC FOR EOT ON READS. ; ; TL069 -- CHECK THAT A CANCEL IS ISSUED BY THE TASK ; WHICH ISSUED THE CURRENT OPERATION ; ; TL070 -- RETURN THE CORRECT BLOCK COUNT FOR ; IO.SPB AT EOV ; ; TL071 -- FIX BRANCH OUT OF RANGE ; ; TL074 -- DO NOT LOG DATA OVERRUN ; ; TL075 -- RETURN EOV FOR IO.SPF, NOT EOT ; ; CS001 -- TAPE DENSITY SUPPORT IDENTIFICATION IN U.CW3 ; ; CS002 -- DEVICE NOT READY IF TAPE UNIT OFF LINE ; ; CS003 -- BOT STATUS IF TAPE UNIT READY ; ; CS004 -- REMOVE REDUNDANT CODE, ; S2.ACT NOT BEING RESET IN S.ST2. ; ; CS005 -- IO.STC/IO.SMO 1600BPI NOT ALLOWED ; ALLOW BAD TAPE READ ERROR RECOVERY ; ; CS006 -- CORRECT CS003; BOT STATUS VALID IF ; TAPE UNIT READY .OR. ENDING OPERATION ; ; CS007 -- HANDLE CALL FOR CONTROLLER POWER FAIL (C BIT SET). ; ; ; ; TM11 MAGNETIC TAPE CONTROLLER DRIVER ; ; MACRO LIBRARY CALLS ; .MCALL HWDDF$,PKTDF$,ABODF$,CLKDF$,UCBDF$ HWDDF$ PKTDF$ ABODF$ CLKDF$ UCBDF$ ;DEFINE UCB OFFSETS ; ; EQUATED SYMBOLS ; US.ABO=1 ;ABORT IN PROGRESS - U.STS US.BSP=2 ;INTERNAL BACKSPACE IN PROGRESS - U.STS US.PWF=10 ;POWER FAIL STATUS RETRY=12 ;RETRY COUNT ; ; REGISTER BIT SYMBOLS ; CS.GO=1 ;GO CS.EXM=60 ;EXTENDED MEMORY BITS CS.IE=100 ;INTERRUPT ENABLE CS.RDY=200 ;CONTROLLER READY BIT CS.EVN=4000 ;EVEN PARITY CS.CLR=10000 ;POWER CLEAR CS.DN5=20000 ;556 BPI DENSITY BIT CS.DN8=40000 ;800 BPI DENSITY BIT DS.TUR=1 ;TAPE UNIT READY DS.RWS=2 ;REWINDING DS.HWL=4 ;WRITE LOCK DS.SDN=10 ;SETTLE DOWN DS.7CH=20 ;UNIT IS 7 CHANNEL DS.BOT=40 ;BEGINNING OF TAPE DS.MOL=100 ;MEDIUM ON LINE DS.BTE=400 ;BAD TAPE ERROR DS.RLE=1000 ;RECORD LENGTH ERROR DS.EOT=2000 ;END OF TAPE DETECTED DS.BGL=4000 ;BUS GRANT LATE DS.PAE=10000 ;PARITY ERROR DS.CRE=20000 ;CYCLICAL REDUNDANCY ERROR DS.TM=40000 ;TAPE MARK DETECTED DS.ILG=100000 ;ILLEGAL COMMAND RD.GAP=10000 ;GAP SHUTDOWN IN PROGRESS RD.LPC=40000 ;READ LPC CHARACTER AND RTTBL FLAG ; ; MAG TAPE STATUS REGISTER BIT DEFINITIONS (SENSE AND SET CHARACTERISTIC ; M.PEOV=100000 ;TAPE PAST LOGICAL END OF VOLUME M.AEOV=40000 ;TAPE AT LOGICAL END OF VOLUME M.BOT=20000 ;TAPE AT BOT M.7CH=10000 ;UNIT IS 7 CHANNEL M.1600=4000 ;TAPE DENSITY CONTROL - '0'=800BPI M.HWL=2000 ;HARDWARE WRITE LOCK M.RWD=1000 ;UNIT IS REWINDING M.SER=400 ;SELECT ERROR HAS OCCURED M.IXG=200 ;INHIBIT WRITE WITH EXTENDED INTERRECORD M.SWL=100 ;SOFTWARE WRITE LOCK M.EOF=40 ;LAST COMMAND ENCOUNTERED TAPE MARK M.EOT=20 ;LAST COMMAND ENCOUNTERED EOT M.EVN=10 ;EVEN PARITY M.CDM=4 ;CORE DUMP MODE (7 CHANNEL ONLY) M.200=2 ;200 BPI (7 CHANNEL ONLY) M.556=1 ;556 BPI (7 CHANNEL ONLY) USRBTS=317 ;STATUS BITS CONTROLLED BY THE USER NEWBTS=M.PEOV!M.BOT!M.EOF!M.EOT ;STATUS BITS TO BE SET BEFORE $IODON ; ; COMMANDS ; RWU=101 ;REWIND AND OFFLINE RED=103 ;READ WRT=105 ;WRITE WEF=107 ;WRITE END-OF-FILE SPF=111 ;SPACE FORWARD SPR=113 ;SPACE REVERSE WTE=115 ;WRITE WITH EXTENDED GAP RWD=117 ;REWIND U.SPC = U.VCB+2 ;SPACING COUNT, RDBLK TEMP. ; ; LOCAL MACROS ; ; ; THE FOLLOWING MACRO DEFINES ENTRIES IN THE FUNCTION TABLE ; .MACRO DFENT COM,TIMOUT,PWF,OPCODE,TYPE,INTADD .WORD COM .BYTE PWF,TIMOUT .BYTE TYPE,OPCODE .WORD INTADD .ENDM DFENT ; ; LOCAL DATA ; ; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLLER NUMBER) ; ; DIAGNOSTIC FUNCTIONS USE BITS 14-15 OF RTTBL AS FLAGS FOR ; INTERRUPT AND FUNCTION HANDLING. RTTBL: .BLKW T$$M11 ;ERROR RETRY COUNT SPTBL: .BLKW T$$M11 ;FOR SPACE CHECKING INTADD: .BLKW T$$M11 ;CURRENT INTERRUPT SERVICE ADDRESS ; ; LEGAL FUNCTION DISPATCH TABLE ; LGFCN: DFENT IO.RLB,8.,0,RED,0,RDBLK ;READ LOGICAL BLOCK DFENT IO.WLB,6.,0,WRT,0,WRBLK ;WRITE LOGICAL BLOCK DFENT IO.EOF,2.,0,WEF,0,WREOF ;WRITE TAPE MARK DFENT IO.RWD,2.,1,RWD,0,REWND ;REWIND DFENT IO.RWU,2.,1,RWU,0,REWND ;REWIND THEN OFF-LINE DFENT IO.SPB,8.,0,SPF,1,SPCBK ;SPACE BLOCK DFENT IO.SPF,8.,0,SPF,2,SPCFL ;SPACE FILE DFENT IO.STC,0,-1,0,-1,-1 ;SET CHARACTERISTICS DFENT IO.SEC,0,-1,1,-1,-1 ;SENSE CHARACTERISTICS DFENT IO.SMO,0,1,-1,-1,-1 ;MOUNT AND SET CHARACTERISTICS ENDFCN=. ;END OF FUNCTION TABLE ; ; DRIVER DISPATCH TABLE ; DDT$ MT,T$$M11 ;GENERATE DISPATCH TABLE ;+ ; **-MTINI-TM11 MAGNETIC TAPE CONTROLLER INITIATOR ; ; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O REQUE ; IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO PROPAGATE THE ; TION OF THE DRIVER. IF THE SPECIFIED CONTROLLER IS NOT BUSY, THEN AN A ; IS MADE TO DEQUEUE THE NEXT I/O REQUEST. ELSE A RETURN TO THE CALLER I ; EXECUTED. IF THE DEQUEUE ATTEMPT IS SUCCESSFUL, THEN THE NEXT I/O OPER ; ATION IS INITIATED. A RETURN TO THE CALLER IS THEN EXECUTED. ; ; INPUTS: ; ; R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED. ; ; OUTPUTS: ; ; IF THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O REQUEST IS WA ; ING TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED AND THE I/O OP ; ATION IS INITIATED. ;- .ENABL LSB MTINI: GTPKT$ MT,T$$M11 ;GET NEXT I/O PACKET TO PROCESS ; ; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT: ; ; R1=ADDRESS OF THE I/O REQUEST PACKET. ; R2=PHYSICAL UNIT NUMBER OF THE REQUEST UCB. ; R3=CONTROLLER INDEX. ; R4=ADDRESS OF THE STATUS CONTROL BLOCK. ; R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED. ; ; TM11 MAGNETIC TAPE FUNCTION INDEPENDENT I/O REQUEST PACKET FORMAT: ; ; WD. 00 -- I/O QUEUE THREAD WORD. ; WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER. ; WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTOR TASK. ; WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTOR TASK HEADER. ; WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTOR TASK HEADE ; WD. 05 -- I/O FUNCTION CODE (IO.RLB/IO.RWD/IO.SPB/IO.SPF/IO.EOF) ; WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK. ; WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK. ; WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 14000 ; WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE. ; MOV #$MTCLK,S.MTCK+C.SUB(R4) ;SET ADDR OF CLOCK ROUTINE CLR S.FRK+2(R4) ;INIT FORK PC WORD MOV #LGFCN,R2 ;POINT TO LEGAL FUNCTION TABLE CLRB RTTBL+1(R3) ;CLEAR DIAGNOSTIC FLAG MOV I.FCN(R1),R0 ;GET FUNCTION CODE BITB #IQ.UMD,R0 ;DIAGNOSTIC FUNCTION CALL? BEQ 20$ ;IF EQ NO MOV #100000,RTTBL(R3) ;STOP RETRIES AND SET DIAG. FLAG CMP #IO.LPC!IQ.UMD,R0 ;READ LPC CHARACTER FUNCTION? BNE 15$ ;IF NE NO BIS #RD.LPC,RTTBL(R3) ;SET LPC READ FLAG MOV #IO.RLB!IQ.UMD,R0 ;CONVERT TO READ LOGICAL MOV R0,I.FCN(R1) ;SAVE FOR LATER USE 15$: BIC #IQ.UMD,R0 ;CLEAR FOR FUNCTION CHECK 20$: BICB #IQ.X,R0 ;CLEAR IQ.X WILL BE TESTED LATER CMP R0,(R2)+ ;FUNCTION MATCH? BEQ 35$ ;IF EQ YES ADD #6,R2 ;POINT TO NEXT TABLE ENTRY CMP R2,#ENDFCN ;AT END OF TABLE? BNE 20$ ;IF NE NO BR 40$ ;ILLEGAL FUNCTION JMP 230$ ;FINISH IN COMMON CODE ; ; FUNCTION CODE MATCH FOUND ; 35$: BITB #US.PWF,U.STS(R5) ;POWER FAIL OCCUR? BEQ 45$ ;IF EQ NO TSTB (R2) ;LEGAL FUNCTION? BMI 45$ ;IF MI YES BNE 43$ ;IF NE THIS IS A BETTER ONE 40$: MOV #IE.IFC&377,R0 ;NO JMP 230$ ;INFORM THE USER 43$: BICB #US.PWF,U.STS(R5) ;ALLOW ALL FUNCTIONS 45$: MOV (R2)+,S.CTM(R4) ;SET UP FOR PROPER TIMEOUT CLRB S.CTM(R4) ;CLEAR OUT PWF INFO CLR SPTBL(R3) ;RESET SPACING FLAG CLR U.SPC(R5) ;NOT SPACING FILE TSTB (R2)+ ;DETERMINE TYPE OF OPERATION BPL 50$ ;IF PL NOT STATUS FUNCTION JMP 190$ ;STATUS FUNCTION 50$: BEQ 90$ ;IF EQ NON-SPACING FUNCTION ; ; SPACING FUNCTION DEPENDENT I/O PACKET FORMAT: ; ; WD. 12 -- SPACING COUNT (POSITIVE=FORWARD, NEGATIVE=BACKWARD). ; WD. 13 -- NOT USED. ; WD. 14 -- NOT USED. ; WD. 15 -- NOT USED. ; WD. 16 -- NOT USED. ; WD. 17 -- RELOCATON BIAS OF DIAGNOSTIC REG. BLK. ADDRESS ; WD. 20 -- DIAG. REG. BUFFER ADDRESS (REAL OR DISPL. + 140000) ; BISB #S3.SIP,S.ST3(R4) ;SET POSITIONING IN PROGRESS MOV U.BUF(R5),I.PRM+4(R1) ;MOVE SPACING COUNT TO COMMON PLAC CLR U.BUF(R5) ;RESET TO TAKE ON OPCODE BELOW MOV I.PRM+4(R1),U.CNT(R5) ;MOVE SPACING COUNT TO COMMON PLAC BNE 60$ ;IF NE SOME SPACING REQUIRED CLR I.PRM+4(R1) ;CLEAR COUNT FOR STATUS RETURN JMP 220$ ;NO SPACING REQUIRED 60$: BMI 65$ ;IF MI SPACE REVERS BIT #M.AEOV,U.CW2(R5) ;AT EOV? BEQ 70$ ;IF EQ NO - PROCEED MOV #IE.EOV&377,R0 ;STILL AT EOV CLR I.PRM+4(R1) ;CLEAR COUNT FOR STATUS RETURN JMP 230$ ;TELL THE USER 65$: ;REFERENCE LABEL NEG U.CNT(R5) ;CONVERT TO POSITIVE COUNT NEG I.PRM+4(R1) ;THIS ONE, TOO BIS #2,U.BUF(R5) ;CHANGE SPACE FORWARD TO SPACE REVERSE 70$: CMPB -1(R2),#1 ;SPACE FILE OR SPACE BLOCK? BEQ 80$ ;IF EQ SPACE BLOCK MOV U.CNT(R5),U.SPC(R5) ;SAVE COUNT OF FILES TO SPACE NEG U.SPC(R5) ;SET UP FOR FINAL ACCOUNTING MOV #-1,U.CNT(R5) ;SET UP FOR BIG SPACE 80$: MOV U.CNT(R5),SPTBL(R3) ;SAVE SPACING COUNT NEG SPTBL(R3) ;MAKE IT MATCH REGISTER CONTENTS BR 110$ ;SKIP SOME CHECKS AND BIC'S ; ; READ/WRITE LOGICAL FUNCTION DEPENDENT I/O PACKET FORMAT: ; ; WD. 12 -- RELOCATION BIAS OF DATA BUFFER. ; WD. 13 -- DATA BUFFER ADDRESS. ; WD. 14 -- NUMBER OF BYTES TO BE TRANSFERED. ; WD. 15 -- NOT USED. ; WD. 16 -- NOT USED. ; WD. 17 -- NOT USED. ; WD. 20 -- RELOCATON BIAS OF DIAGNOSTIC REG. BLK. ADDRESS ; WD. 21 -- DIAG. REG. BUFFER ADDRESS (REAL OR DISPL. + 140000) ; ; NO FUNCTION DEPENDENT PARAMETERS ARE REQUIRED FOR REWIND OR WRITE EOF ; 90$: ;REF LABEL .IF DF M$$EXT CALL $STMAP ;SET UP UNIBUS MAPPING ADDRESS .ENDC CMPB -2(R2),#2 ;WRITE EOF, REWIND OR REWIND & OFFLINE? BEQ 100$ ;IF EQ YES - SEE IF WRITELOCK SET CMPB (R2),#WRT ;WRITE? BNE 110$ ;IF NE NO MOV #IE.SPC&377,R0 ;ASSUME PARAMETER PROBLEMS CMP I.PRM+4(R1),#14. ;TOO SHORT? BLO 163$ ;IF LO YES BR 105$ ;SKIP EXMEM BIT CLEAR 100$: CLR U.BUF(R5) ;NOTHING THERE FOR WEF BISB #S3.SIP,S.ST3(R4) ;SET POSITIONING IN PROGRESS CMPB (R2),#WEF ;WRITE EOF? BNE 110$ ;IF NE NO, SKIP CHECK FOR WRITE LOCK 105$: MOV #IE.WLK&377,R0 ;ASSUME (SOFTWARE) WRITE LOCK BIT #M.SWL,U.CW2(R5) ;LOCKED? BNE 163$ ;IF NE YES 110$: BISB (R2)+,U.BUF(R5) ;PICK UP FUNCTION CODE FROM COMMAND TABL MOV (R2),INTADD(R3) ;SET INITIAL INTERRUPT ADDRESS TST RTTBL(R3) ;DIAGNOSTIC FUNCTION? BMI 120$ ;IF MI YES, STOP RETRIES MOV #RETRY,RTTBL(R3) ;SET UP RETRY COUNTS 120$: CALL SELECT ;SELECT THE REQUIRED DRIVE BCS SELERR ;IF CS SELECT ERROR OCCURRED MOV U.CW2(R5),R1 ;PICK UP DRIVE'S CHARACTERISTICS BIT #M.EVN,R1 ;EVEN PARITY REQUIRED? BEQ 140$ ;IF EQ NO BIS #CS.EVN,U.BUF(R5) ;SET BIT IN STATUS REGISTER 140$: BIS #CS.DN5!CS.DN8,U.BUF(R5) ;ASSUME 9-CHANNEL, 800BPI BIT #M.7CH,R1 ;7-CHANNEL DRIVE? BEQ 170$ ;IF EQ NO BIT #M.CDM,R1 ;CORE DUMP MODE? BNE 170$ ;IF NE YES BIT #M.556,R1 ;556 BPI? BNE 150$ ;IF NE YES BIC #CS.DN5,U.BUF(R5) ;RESET BIT FOR COMMAND BIT #M.200,R1 ;200 BPI? BEQ 170$ ;IF EQ NO 150$: BIC #CS.DN8,U.BUF(R5) ;RESET COMMAND BIT BR 170$ ; ; DEVICE TIMEOUT RESULTS IN THE CURRENT OPERATION BEING TERMINATED. ; IF THE OPERATION WAS DIAGNOSTIC, THE QIO REQUEST IS TERMINATED. ; TIMEOUTS ARE USUALLY CAUSED BY POWERFAILURE BUT MAY ALSO BE THE ; RESULT OF HARDWARE CONSIDERATIONS. IN PARTICULAR, A LENGTHY SPACING ; OPERATION MAY RESULT IN A TIMEOUT WHICH WILL BE IGNORED. ; MTOUT: MOV S.CSR(R4),R2 ;;;PICK UP ADDRESS OF CSR BITB #US.ABO,U.STS(R5) ;;;ABORTING? BEQ 152$ ;;;IF EQ NO BIC #M.RWD,U.CW2(R5) ;;;REWIND NOT IN PROGRESS BR 162$ ;;;TERMINATE 152$: ;;;REFERENCE LABEL MOVB S.CON(R4),R3 ;;;FETCH CONTROLLER NO. BIT #M.RWD,U.CW2(R5) ;;;REWINDING? BNE 155$ ;;;IF NE YES MOV SPTBL(R3),R0 ;;;SPACE IN PROGRESS? BEQ 154$ ;;; IF EQ THEN NO CMP R0,2(R2) ;;;IS THE TAPE BLANK? BNE 153$ ;;; IF NE THEN NO CALL $DTOER ;;; LOG DEVICE TIMEOUT BR 161$ ;;; EXIT WITH IE.DNR ERROR CODE 153$: ;;; REF. LABEL MOV 2(R2),SPTBL(R3) ;;;SAVE VALUE FOR NEXT COMPARISON MOVB S.ITM(R4),S.CTM(R4) ;;;RESUME TIMEOUT RETURN ;;;THAT IS ALL FOR NOW 154$: CALL $DTOER ;;; LOG DEVICE TIMEOUT BCS 161$ ;IF CS ABORT DIAGNOSTIC FUNCTION 155$: BIC #CS.IE,(R2) ;;;CLEAR INTERRUPT ENABLE MTPS #0 ;;;ALLOW INTERRUPTS BIT #M.SER,U.CW2(R5) ;WAS THERE A SELECT ERROR? BEQ 160$ ;IF EQ NO BIC #M.SER,U.CW2(R5) ;RESET STATUS BIT BIT #M.RWD,U.CW2(R5) ;REWINDING? BEQ 120$ ;IF EQ NO - REISSUE ORIGINAL COMMAND BIT #DS.MOL,-2(R2) ;IS THE DRIVE ON-LINE NOW? BEQ SELERR ;IF EQ NO MOVB #RWD-CS.IE,(R2) ;START THE REWIND AGAIN BR 172$ ;START UP TIMEOUT 160$: BIT #M.RWD,U.CW2(R5) ;REWINDING? BNE 164$ ;IF NE YES 161$: MOV #IE.DNR&377,R0 ;INDICATE DEVICE NOT READY 162$: CALL MTDINT ;PASS DIAGNOSTIC DEVICE REGISTERS BIS #CS.CLR,(R2) ;RESET CONTROLLER 163$: JMP 230$ ;REPORT FATAL ERROR 164$: BIT #DS.MOL,-2(R2) ;EVERYTHING COPASETIC? BEQ SELERR ;IF EQ NO BIT #DS.BOT!DS.RWS,-2(R2) ;TAPE OK? BNE 165$ ;IF NE OK SELERR: MOV #IE.DNR&377,R0 ;NOT READY - IF TAPE OFF LINE TST RTTBL(R3) ;DIAGNOSTIC FUNCTION? BMI 230$ ;IF MI YES, STOP THE SELECT MESSAGE BITB #IQ.X,I.FCN(R1) ;SUPPRESS RETRIES? BNE 230$ ;IF NE YES SKIP SELECT MSG. TST U.ACP(R5) ; ACP WANTS RETURN IMMEDIATE? BNE 230$ ; IF NE YES EXIT DEVICE NOT READY BIS #M.SER,U.CW2(R5) ;SET SELECT ERROR BIT DECB S.STS(R4) ;TIME FOR A MSG? BNE 172$ ;IF NE NO MOV #T.NDSE,R0 ;SET UP TO DELIVER MESSAGE MOVB #15.,S.STS(R4) ;SET UP TIMEOUT CALL $DVMSG ;SEND THE MESSAGE BR 172$ ;SET THE TIMOUT 165$: BIT #DS.TUR,-2(R2) ;REWIND COMPLETE? BEQ 172$ ;IF EQ NO BIT #DS.BOT,-2(R2) ;DID WE GET TO BOT? BNE 175$ ;IF NE YES - REWIND COMPLETE 170$: BIT #M.RWD,U.CW2(R5) ;REWINDING? BEQ 177$ ;IF EQ NO 172$: MOVB #1,S.CTM(R4) ;SET UP A TIMEOUT RETURN ;THAT IS ALL FOR NOW 175$: BIS #M.BOT,U.CW2(R5) ;SAY AT BOT 177$: ;REF LABEL .IF DF M$$EXT CMPB #SPF,U.BUF(R5) ;SPACE FORWARD? BEQ 178$ ;IF EQ YES, UMR'S NOT NEEDED CMPB #SPR,U.BUF(R5) ;SPACE FORWARD? BEQ 178$ ;IF EQ YES, UMR'S NOT NEEDED MOV R2,-(SP) ;SAVE R2 CALL $MPUBM ;MAP UNIBUS TO TRANSFER MOV (SP)+,R2 ;RESTORE R2 .ENDC 178$: CMP (R2)+,(R2)+ ;POINT TO MEMORY ADDRESS REGISTER MOV U.BUF+2(R5),(R2) ;SET UP BUFFER ADDRESS MOV U.CNT(R5),-(R2) ;SET UP BYTE COUNT REGISTER NEG (R2) ;NEED 2S COMPLEMENT 180$: MOVB S.ITM(R4),S.CTM(R4) ;SET CURRENT DEVICE TIMEOUT COUNT BIC #M.AEOV!M.SER!M.RWD,U.CW2(R5) ;RESET VARIOUS FLAGS BICB #US.BSP,U.STS(R5) ;RESET FLAGS BIT #RD.LPC,RTTBL(R3) ;READ LPC CHAR FUNCTION? BEQ 185$ ;IF EQ NO BIS #RD.LPC,6(R2) ;SET LPC READ IN MTRD REG. 185$: CALL $BMSET ;SET I/O ACTIVE FLAG MOV U.BUF(R5),-(R2) ;INITIATE THE FUNCTION RETURN ;DONE ; ; CANCEL I/O OPERATION IS A NOP FOR TM11 MAGNETIC TAPES ; MTCAN: CMP I.TCB(R0),R1 ;CANCEL FOR THIS TASK? BNE 111$ ;BRANCH IF NOT BISB #US.ABO,U.STS(R5) ;FLAG THE ABORT CONDITION 111$: RETURN ; ; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND THEREFORE CAU ; NO IMMEDIATE ACTION ON THE DEVICE. THIS IS DONE TO AVOID A RACE CONDIT ; THAT COULD EXIST IN RESTARTING THE I/O OPERATION. ; MTPWF: BCS 112$ ;IF CS, CONTROLLER POWER FAIL. BISB #US.PWF,U.STS(R5) ; ELSE, UNIT POWER FAIL ; DISALLOW NORMAL QIO'S. CALL DRVSTS ;INDICATE TAPE DENSITY SUPPORT 112$: RETURN ; ; STATUS FUNCTION PROCESSING ; 190$: ;REFERENCE LABEL MOV R2,-(SP) ;SAVE TABLE POINTER CALL SELECT ;SET BOT, HWL, AND 7CH STATUS MOV (SP)+,R2 ;RESTORE POINTER MOV U.CW2(R5),I.PRM+4(R1) ;ASSUME SENSE CHARACTERISTICS TSTB (R2)+ ;DETERMINE FUNCTION REQUIRED BEQ 210$ ;IF EQ SET CHARACTERISTICS BPL 220$ ;IF PL "SENSE CHARACTERISTICS" 201$: BIT #M.BOT,U.CW2(R5);AT BOT? BNE 210$ ;IF NE, YES. 203$: MOV #IE.FHE&377,R0 ;FATAL ERROR, BR 230$ ; END REQUEST. 210$: BIT #M.1600,U.BUF(R5) ;TRYING TO SET 1600BPI? BNE 203$ ;IF NE, YES - NOT ALLOWED. BIC #USRBTS,U.CW2(R5) ;PREPARE TO SET NEW BITS. BIC #^C,U.BUF(R5) ;LEAVE ONLY USER CONTROLLED BITS BIS U.BUF(R5),U.CW2(R5) ;NEW STATUS WORD ; ; NO SPACING REQUIRED ; 220$: MOV #IS.SUC&377,R0 ;SET SUCCESSFUL COMPLETION STATUS 230$: MOV S.CSR(R4),R2 ;PICK UP CSR ADDRESS BIC #CS.IE!CS.EXM,(R2) ;CLEAR INT. ENABLE AND EX. MEM BITS CLR 2(R2) ;ASSURE PROPER VALUE FOR RETURN JMP 540$ ;CLEAN UP AND EXIT ;+ ; **-$MTINT-TM11 MAGNETIC TAPE CONTROLLER INTERRUPTS ;- INTSE$ MT,PR5,T$$M11 ;;;GENERATE INTERRUPT SAVE CODE MOV U.SCB(R5),R4 ;;;RETRIEVE ADDRESS OF SCB TST S.FRK+2(R4) ;;;HAVE WE FORKED ALREADY? BNE 300$ ;;;IF NE YES, RETURN FROM INTERRUPT CALL $FORK ;;;CREATE A SYSTEM PROCESS 240$: MOV U.SCB(R5),R4 ;GET SCB ADDRESS MOV S.CSR(R4),R2 ;PICK UP COMMAND REGISTER ADDRESS BIT #DS.TUR!DS.RWS!DS.ILG!DS.EOT!DS.BOT,-(R2) ;UNIT DONE? BNE 250$ ;IF NE YES CMPB U.BUF(R5),#RWU ;WAS IT A REWIND AND OFFLINE FUNCTION? BEQ 220$ ;IF EQ YES, COMPLETE WITH SUCCESS MOV R4,R0 ;GET ADDR OF CLOCK QUEUE BLOCK ADD #S.MTCK,R0 ; CLR R1 ;SET UP HIGH TICKS MOV #1,R2 ;TIMEOUT UNTIL TUR MOV #C.SYST,R4 ;TYPE OF CLOCK ENTRY CALLR $CLINS ;TIMEOUT $MTCLK:: ;REF LABEL FOR TIMEOUT MOV C.TCB(R4),R5 ;RESTORE UCB ADDRESS BR 240$ ;SEE IF UNIT READY 250$: MOVB S.CON(R4),R3 ;PICK UP CONTROLLER NO. BIT #DS.MOL,(R2)+ ;IS THE DRIVE STILL ON-LINE? BNE 260$ ;IF NE YES JMP 161$ ;ISSUE "DEVICE-NOT-READY" MSG 260$: BIC #CS.IE!CS.EXM,(R2) ;CLEAR INT. ENABLE AND EX.MEM BITS MOVB S.ITM(R4),S.CTM(R4) ;RESET TIMEOUT COUNT CLR S.FRK+2(R4) ;ALLOW INTERRUPT PROCESSING MOV -2(R2),R1 ;GET CONTENTS OF DRIVE STATUS REGISTER BITB #US.BSP,U.STS(R5) ;INTERNAL BACKSPACE IN PROGRESS? BNE 280$ ;IF NE YES - CALL SERVICE ROUTINE 270$: MOV #IS.SUC&377,R0 ;ASSUME SUCCESS FOR VARIOUS REASONS TST (R2) ;ANY ERRORS? BMI 280$ ;IF MI YES TST U.SPC(R5) ;SPACING FILE? BNE 280$ ;IF NE, YES. TREAT AS ERROR ANYWAY. CMPB (R2),#RWD+CS.RDY-CS.GO-CS.IE ;WAS THAT A REWIND? BNE 275$ ;IF NE NO BIS #M.RWD,U.CW2(R5) ;SET STATUS BIT 275$: JMP 500$ ;SUCCESS!! 280$: TST RTTBL(R3) ;DIAGNOSTIC FUNCTION? BMI 290$ ;IF MI YES BIT #DS.ILG!DS.CRE!DS.PAE!DS.BGL!DS.BTE,R1 ; ANY ERRORS IN STATUS REG (MTS)? BEQ 290$ ; IF EQ THEN NO CALL $DVERR ; LOG DEVICE ERROR 290$: CALL @INTADD(R3) ;CALL THE INTERRUPT ROUTINE BIS #S2.ACT,S.ST2(R4) ;SET I/O ACTIVE FLAG MOV (SP)+,INTADD(R3) ;SAVE INTERRUPT ADDRESS 300$: RETURN ;WAIT FOR END OF NEXT COMMAND STEP ; ; WRITE LOGICAL FUNCTION ; WRBLK: BIT #DS.TM,R1 ;DID WRITE SEE EOF? BNE 320$ ;IF NE YES ; ; WRITE TAPE MARK FUNCTION ; WREOF: BIT #34404,R1 ;ANY OTHER ERRORS? BEQ 325$ ;IF EQ NO - REALLY SUCCESSFUL MOV #IE.WLK&377,R0 ;ASSUME WRITE-LOCK BIT #DS.HWL,R1 ;WRITE LOCK? BNE 325$ ;IF NE YES BIT #34400,R1 ;RECOVERABLE ERROR? BNE 320$ ;IF NE YES ; ; REWIND FUNCTIONS ; REWND: MOV #IE.FHE&377,R0 ;FATAL ERROR BR 325$ ; .. CONT 320$: MOV #IE.BBE&377,R0 ;ASSUME BAD TAPE OR EQUIVALENT TSTB U.CW2(R5) ;SHOULD WE REWRITE? BMI 325$ ;IF MI, NO. BIT #2,@R2 ;IS THIS A WRITE EOF? BNE 420$ ;IF NE YES BIS #WTE-WRT,U.BUF(R5) ;DO WRITE WITH EXTENDED GAP FROM NOW BR 420$ ;DO THE OPERATION ; 325$: BR 490$ ;GO FINISH UP INT SERVICE ; ; SPACE FILE FUNCTION ; SPCFL: BIT #DS.TM,R1 ;TAPE MARK ENCOUNTERED? BNE 350$ ;IF NE YES MOV U.SPC(R5),2(R2) ;SOMETHING ELSE STOPPED US ; ; SPACE BLOCK FUNCTION ; SPCBK: BIT #DS.BOT,R1 ;AT BOT? BNE 490$ ;IF NE YES, NOT AN ERROR, BUT NEED STACK BIT #DS.TM,R1 ;EOF? BEQ 340$ ;IF EQ NO CALL CHKEOV ;SEE IF AT END OF VOLUME BCC 410$ ;IF CC NOT FOUND BR 360$ ;POSITION TAPE AT EOV 340$: BIT #DS.BTE!DS.EOT,R1 ;BAD TAPE ERROR OR EOT? BNE RDBLK ;IF NE YES - NOT RECOVERABLE BR REWND ;FATAL 350$: CALL CHKEOV ;DID TAPE REACH LOGICAL END OF VOLUME? BCC 370$ ;IF CC NO, TRY NEXT FILE 360$: CALL BSPACE ;BACKSPACE THE TAPE CALL @(SP)+ ;WAIT FOR COMPLETION MOV #IE.EOV&377,R0 ;INFORM USER THAT EOV HAS BEEN DETECTED BIS #M.AEOV,U.CW2(R5) ;SET STATUS BIT BR 380$ ;FIX COUNT AND RETURN 370$: INC U.SPC(R5) ;ANOTHER TAPE MARK DETECTED BNE 390$ ;IF NE NOT DONE 380$: MOV U.SPC(R5),2(R2) ;SET UP FINAL COUNT MOV S.PKT(R4),R3 ;GET THE I/O PACKET ADDRESS MOV I.FCN(R3),-(SP) ;GET THE FUNCTION CODE BIC #IQ.UMD!IQ.X,(SP) ;CLEAR EXTRA BITS CMP #IO.SPB,(SP)+ ;SPACE BLOCKS? BNE 385$ ;NO -- LEAVE STATUS ALONE CLR I.PRM+4(R3) ;CLEAR FOR STATUS RETURN CLR 2(R2) ;... 385$: BR 490$ ;RETURN TO USER 390$: BIS #M.EOF,U.CW2(R5) ;I SAW AN EOF MOV #1,2(R2) ;SET RECORD COUNT FOR SPACING MOV 2(R2),SPTBL(R3) ;SAVE RECORD COUNT ADD #-CS.RDY+CS.GO+CS.IE,(R2) ;REISSUE SPACING COMMAND CALL @(SP)+ ;WAIT FOR COMPLETION BR SPCFL ;SEE WHAT HAPPENED ; ; READ LOGICAL FUNCTION ; RDBLK: MOV #IE.BBE&377,R0 ;ASSUME BAD TAPE BIT #DS.BTE,R1 ;BAD TAPE/OPI? BEQ 405$ ;IF EQ, NO. CMP 2(R2),U.CNT(R5) ;BAD TAPE? BNE 420$ ;IF NE, YES. BR REWND ; ELSE - OPI. 405$: MOV #IE.DAO&377,R0 ;ASSUME RECORD LENGHT ERROR. BIT #DS.RLE,R1 ;RECORD LTH ERROR? BNE 490$ ;IF NE YES 410$: MOV #IE.EOF&377,R0 ;TRY EOF BIT #DS.TM,R1 ;EOF DETECTED? BNE 490$ ;IF NE YES MOV #IS.SUC&377,R0 ;ASSUME SUCCESS FOR EOT'S BIT #DS.EOT,R1 ;EOT? BNE 490$ ;IF NE NO MOV #IE.VER&377,R0 ;ASSUME DATA ERROR 420$: MOV R1,-(SP) ;SAVE R1 MOV S.PKT(R4),R1 ;RETREIVE I/O PACKRT ADDRESS BITB #IQ.X,I.FCN(R1) ;RETRIES SUPPRESSED? BEQ 430$ ;IF EQ NO CONTINUE MOV (SP)+,R1 ;RESTORE R1 BR 490$ ;EXIT 430$: MOV (SP)+,R1 ;RESTORE R1 DECB RTTBL(R3) ;DECREMENT RETRY COUNT BLE 490$ ; IF LE NO MOV INTADD(R3),U.SPC(R5) ;SAVE ORIGINAL ADDRESS CALL BSPACE ;BACKSPACE THE TAPE CALL @(SP)+ ;WAIT FOR BACKSPACE MOV U.SPC(R5),INTADD(R3) ;RESTORE INT ADDRESS CLR U.SPC(R5) ;RESET TO INDICATE NOT SPACING FILE TST (SP)+ ;CLEAN UP THE STACK JMP 177$ ;RETRY ; ; END OF INTERRUPT SERVICE ROUTINE PROCESSING ; 490$: TST (SP)+ ;CLEAN UP THE STACK 500$: MOV R5,R3 ;MAKE A COPY OF UCB BASE ADD #U.CW2,R3 ;COMPUTE OFFSET TO MAG TAPE STATUS MOV (R3),-(SP) ;SAVE CURRENT STATUS BIC #NEWBTS,(R3) ;CLEAR STATUS BITS TO BE DETERMINED BIT #DS.BOT,R1 ;AT BOT? BEQ 510$ ;IF EQ NO BIS #M.BOT,(R3) ;SET STATUS BIT 510$: BIT #DS.TM,R1 ;TAPE MARK? BEQ 520$ ;IF EQ NOT TAPE MARK CMPB (R2),#SPR+CS.RDY-CS.IE-CS.GO ;WAS THAT A BACKSPACE? BEQ 520$ ;IF EQ YES - DON'T SET INTERNAL EOF BIT BIS #M.EOF,(R3) ;SET STATUS BIT 520$: MOV R1,-(SP) ;SAVE R1 CALL MTDINT ;PASS DIAGNOSTIC DEVICE REGISTERS MOV (SP)+,R1 ;RESTORE R1 BCS 530$ ;IF CS FUNCTION WAS DIAGNOSTIC BIT #DS.ILG!DS.CRE!DS.PAE!DS.BGL!DS.BTE,R1 ; ANY ERRORS IN STATUS REG (MTS)? BEQ 530$ ; IF EQ THEN NO CALL $DVERR ; LOG DEVICE ERROR 530$: CMPB (R2),#RED+CS.RDY-CS.IE-CS.GO ;WAS THAT A READ? BEQ 539$ ;IF EQ YES, IGNORE EOT BIT #DS.EOT,R1 ;EOT? BEQ 539$ ;IF EQ NO TSTB R0 ;ALREADY RETURNING AN ERROR? BMI 538$ ;IF MI YES 535$: MOV #IE.EOT&377,R0 ;SET FOR EOT STATUS 538$: BIS #M.EOT,(R3) ;REMEMBER EOT FOR NEXT COMMAND MOV 2(R2),-(SP) ;PRESERVE THE COUNT REGISTER BIS #CS.CLR,@R2 ;STOP THE DRIVE IF RUNNING AWAY MOV (SP)+,2(R2) ;RESTORE THE COUNT REGISTER 539$: TST (SP)+ ;CLEAN STACK 540$: MOV S.PKT(R4),R1 ;RETRIEVE ADDRESS OF I/O PACKET BICB #S3.SIP,S.ST3(R4) ;RESET POSITIONING INPROGRESS BIC #S2.ACT,S.ST2(R4) ; CLEAR I/O ACTIVE. MOV I.PRM+4(R1),R1 ;GET ORIGINAL COUNT VALUE ADD 2(R2),R1 ;FIX COUNT REMAINING MOVB S.CON(R4),R3 ; RETRIEVE CONTROLLER INDEX MOVB RTTBL(R3),R2 ; GET FINAL RETRY COUNT BIS #RETRY*256.,R2 ; MERGE STARTING RETRY COUNT CALL $IODON ;FINISH I/O OPERATION JMP MTINI ;GO AGAIN .DSABL LSB ; ; THIS SUBROUTINE CHECKS FOR THE LOGICAL END-OF-VOLUME CONDITION ; ; RETURNS WITH CC IF NOT EOV. ; RETURNS WITH CS IF EOV. ; CHKEOV: MOV 2(R2),-(SP) ;SAVE FRAME COUNT ADD U.CNT(R5),(SP) ;GET NUMBER ACTUALLY SPACED CMP (SP)+,#1 ;EXACTLY ONE? (COUNT STARTED WITH 1) CLC ;ASSUME NOT EOV BNE 30$ ;IF NE NO, NOT EOV .IF DF A$$NSI BITB #US.LAB,U.STS(R5) ;MOUNTED ANSII TAPE? BNE 30$ ;IF NE YES - EXIT WITH CC .ENDC BIT #2,(R2) ;FORWARD SPACE? BNE 30$ ;IF NE NO - CANNOT BE EOV BIT #M.EOF!M.BOT,U.CW2(R5) ;AT EOV? BEQ 30$ ;IF EQ NO - EXIT WITH CC SEC ;EOV DETECTED 30$: RETURN ; ; ; THIS SUBROUTINE ISSUES A COMMAND TO BACKSPACE ONE RECORD ; BSPACE: BISB #US.BSP,U.STS(R5) ;SET INTERNAL BACKSPACE IN PROGRESS MOV #-1,2(R2) ;BACKSPACE ONE RECORD MOVB #SPR,(R2) ;ISSUE BACKSPACE FUNCTION RETURN ; ; THIS ROUTINE ATTEMPTS TO SELECT A TAPE DRIVE. ; THE CURRENT STATUS OF THE DRIVE WITH REGARD TO 7CH, ; BOT, AND HWL IS SET AT THIS TIME. ; ; ON RETURN: CC==>GOOD SELECT ; CS==>BAD SELECT ; SELECT: CALL DRVSTS ;GET TAPE UNIT STATUS MOVB 1(R2),U.BUF+1(R5) ;SET UP FOR COMMAND MOV -2(R2),-(SP) ;SAVE TAPE UNIT STATUS. BIC #,U.CW2(R5) ;CLEAR EXCESS SEC ;ASSUME SELECT ERROR BIT #DS.MOL,(SP) ;DID DRIVE SELECT? BEQ 10$ ;IF EQ NO - SELECT ERROR BIT #DS.TUR!DS.RWS!DS.SDN,(SP) ;MAKE SURE DRIVE IS OK BNE 7$ ;IF NE OK BIT #RD.GAP,10(R2) ;LAST CHANCE BEQ 10$ ;IF EQ VACUUM IS GONE - FATAL 7$: BIT #DS.TUR!DS.SDN,(SP) ;TRUST BOT? BNE 8$ ;IF NE, YES. BIC #DS.BOT,(SP) ;MAY BE INTERMITTENT. 8$: SWAB (SP) ;UNIT SELECTABLE. CARRY CLEARED. BIC #^C,(SP) ;CLEAR EXTRA BITS BIS (SP),U.CW2(R5) ; BICB #US.ABO,U.STS(R5) ;NOT ABORTING 10$: INC (SP)+ ;CLEAN UP STACK WITHOUT AFFECTING CARRY BCC 20$ ;IF CC GOOD SELECT BIS #M.SER,U.CW2(R5) ;SET SELECT ERROR BIT 20$: RETURN ; ;+ ; SUBROUTINE SELECTS A TAPE UNIT AND TRIES TO OBTAIN TAPE UNIT STATUS. ; ; IF TAPE UNIT READY, DETERMINE 7/9 TRACK STATUS AND UPDATE U.CW3 ACCORDINGLY ;- DRVSTS: MOV S.CSR(R4),R2 ;R2 - CSR. MOVB U.UNIT(R5),1(R2) ;SELECT TAPE UNIT. MOV #50.,-(SP) ;INTERVAL TILL DEV REG RDY. 5$: DEC (SP) ;INTERVAL OVER ? BNE 5$ ;IF NE, NO. BIT #DS.TUR,-2(R2) ;TAPE UNIT READY? BEQ 10$ ;IF EQ, NO. BITS 0-5 NOT AVAILABLE. MOVB #UD.800,U.CW3(R5) ;INDICATE (ONLY) MOVB #UD.UNS,U.CW3+1(R5) ;9TRACK/800BPI. BIT #DS.7CH,-2(R2) ;7TRACK TAPE UNIT ? BEQ 10$ ;IF EQ, NO. MOVB #UD.200,U.CW3(R5) ;INDICATE 7 TRACK, MOVB #UD.800,U.CW3+1(R5) ;200 TO 800BPI SUPPORT. 10$: TST (SP)+ ;RETURN STACK AS FOUND. RETURN ;+ ; **-MTDINT-TM11 DIAGNOSTIC INTERRUPT AND TIMEOUT HANDLER ; ; IF ENTRY WAS FROM A DIAGNOSTIC CONTROL FUNCTION THEN MOVE I/O ; PACKET WORDS 17-20 TO WORDS 20-21 FOR $CRPAS ROUTINE. ; FOR ANY DIAGNOSTIC FUNCTION PASS THE UNIBUS DEVICE REGISTERS VIA ; THE $CRPAS ROUTINE. ; ; INPUTS ; R2= CSR ADDRESS ; R4= SCB ADDRESS ; ; OUTPUTS ; R1= IO PACKET ADDRESS ;- MTDINT: MOV S.PKT(R4),R1 ;GET I/O PACKET ADDRESS CLC ; BITB #IQ.UMD,I.FCN(R1) ;DIAGNOSTIC FUNCTION CALL? BEQ 4$ ;IF EQ NO MOV R1,-(SP) ;SAVE IO PACKET ADDRESS CMPB #IO.EOF/256.,I.FCN+1(R1) ;WRITE EOF FUNCTION? BEQ 1$ ;IF EQ YES CMPB #IO.RWD/256.,I.FCN+1(R1) ;CNTRL FUNCT.OTHER THAN IO.EOF? BEQ 1$ ;IF EQ YES CALL $CRPAS ;PASS DEVICE REGISTERS TO DIAGNOSTIC MOV (SP)+,R1 ;RESTORE IO PACKET ADDRESS BR 3$ ;RETURN 1$: MOV I.PRM+14(R1),I.PRM+16(R1) ;MOVE WD20 TO WD21 MOV I.PRM+12(R1),I.PRM+14(R1) ;MOVE WD17 TO WD20 2$: CALL $CRPAS ;PASS DEVICE REGISTERS TO DIAGNOSTIC MOV (SP)+,R1 ;RESTORE IO PACKET ADDRESS MOV I.PRM+14(R1),I.PRM+12(R1) ;MOVE WD20 BACK TO WD17 MOV I.PRM+16(R1),I.PRM+14(R1) ;MOVE WD21 BACK TO WD20 3$: BIC #RD.LPC,10(R2) ;CLEAR LPC MODE BIT IN MTRD REG. SEC ;SET DIAGNOSTIC FUNCTION CALL RETURN 4$: RETURN .END